package com.zykj.evaluation.viewmodel

import android.app.Application
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.compose.runtime.Stable
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.zykj.evaluation.R
import com.zykj.evaluation.model.DrawerContent
import com.zykj.evaluation.model.SUBJECT_JSON
import com.zykj.evaluation.model.TodoTask
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import okhttp3.internal.closeQuietly
import javax.inject.Inject


@HiltViewModel
class HomeViewModel @Inject constructor(private val application: Application) : ViewModel() {

    private val _homeViewState = mutableStateOf(HomeViewState())
    val homeViewState: State<HomeViewState> = _homeViewState

    init {
        viewModelScope.launch {
            withContext(Dispatchers.IO) {
                generateJson()
            }
            fetchTabData()
            fetchDrawerData()
            dispatch(HomeAction.TabSwitch(TabEntity.TodoEvaluation))
        }
    }

    private val jsonMap = hashMapOf<TabEntity, String>()

    private fun generateJson() {
        viewModelScope.launch(Dispatchers.IO) {
            jsonMap[TabEntity.TodoEvaluation] = readJson("todo_evaluation.json")
            jsonMap[TabEntity.Correcting] = readJson("correcting.json")
            jsonMap[TabEntity.TodoCorrection] = readJson("todo_correction.json")
            jsonMap[TabEntity.EvaluationDone] = readJson("done.json")
        }
    }

    fun dispatch(homeAction: HomeAction) {
        reduce(state = _homeViewState.value, homeAction = homeAction)
    }

    private fun reduce(state: HomeViewState, homeAction: HomeAction) {
        viewModelScope.launch {
            when (homeAction) {
                is HomeAction.Search -> {

                }
                is HomeAction.FilterSelect -> {
                    when (homeAction.drawerContent) {
                        is DrawerContent.SubjectContent -> {
                            emit(
                                state = state.copy(
                                    filterSelection = state.filterSelection.copy(subjectIndex = homeAction.index)
                                )
                            )
                        }
                        is DrawerContent.ReviewContent -> {
                            emit(
                                state = state.copy(
                                    filterSelection = state.filterSelection.copy(reviewIndex = homeAction.index)
                                )
                            )
                        }
                        is DrawerContent.TimeContent -> {
                            emit(
                                state = state.copy(
                                    filterSelection = state.filterSelection.copy(timeIndex = homeAction.index)
                                )
                            )
                        }
                    }
                }
                is HomeAction.FilterReset -> {
                    emit(
                        state = state.copy(
                            filterSelection = FilterSelection(
                                subjectIndex = 0,
                                reviewIndex = 0,
                                timeIndex = 0
                            )
                        )
                    )
                }
                is HomeAction.TabSwitch -> {
                    emit(
                        state = state.copy(
                            pageData = Gson().fromJson(
                                jsonMap[homeAction.tabEntity],
                                object : TypeToken<List<TodoTask>>() {}.type
                            ) ?: emptyList(), selectedTab = homeAction.tabEntity
                        )
                    )
                }
            }
        }
    }

    private fun readJson(filename: String): String {
        val inputStream = application.assets.open(filename)
        val content = inputStream.readBytes().toString(Charsets.UTF_8)
        inputStream.closeQuietly()
        return content
    }

    private fun emit(state: HomeViewState) {
        _homeViewState.value = state
    }

    private fun fetchDrawerData() {
        viewModelScope.launch {
            val filterDataTemp = FilterData()
            val resources = application.resources
            val arrayOfReviewMethods = arrayListOf(
                DrawerContent.ReviewContent(resources.getString(R.string.all)),
                DrawerContent.ReviewContent(
                    resources.getString(R.string.review_by_teacher)
                ),
                DrawerContent.ReviewContent(
                    resources.getString(R.string.review_by_self)
                ),
                DrawerContent.ReviewContent(
                    resources.getString(R.string.review_in_internet)
                )
            )
            filterDataTemp.reviewList.addAll(arrayOfReviewMethods)
            filterDataTemp.subjectList.add(
                DrawerContent.SubjectContent(
                    content = resources.getString(R.string.all),
                    id = 0,
                    name = "topic",
                    sort = 0
                )
            )
            filterDataTemp.subjectList.addAll(
                Gson().fromJson(
                    SUBJECT_JSON,
                    object : TypeToken<List<DrawerContent.SubjectContent>>() {}.type
                )
            )
            val arrayOf = arrayListOf(
                DrawerContent.TimeContent(resources.getString(R.string.all)),
                DrawerContent.TimeContent(
                    resources.getString(R.string.this_week)
                ),
                DrawerContent.TimeContent(
                    resources.getString(R.string.this_month)
                ),
                DrawerContent.TimeContent(resources.getString(R.string.custom))
            )
            filterDataTemp.timeList.addAll(arrayOf)
            emit(state = homeViewState.value.copy(filterData = filterDataTemp))
        }
    }


    private fun fetchTabData() {
        val arrayListOf = arrayListOf<TabEntity>()
        arrayListOf.add(TabEntity.TodoEvaluation)
        arrayListOf.add(TabEntity.Correcting)
        arrayListOf.add(TabEntity.TodoCorrection)
        arrayListOf.add(TabEntity.CorrectAgain)
        arrayListOf.add(TabEntity.EvaluationDone)
        emit(homeViewState.value.copy(tabList = arrayListOf))
    }
}

data class HomeViewState(
    val filterData: FilterData = FilterData(),
    val filterSelection: FilterSelection = FilterSelection(),
    val tabList: List<TabEntity> = emptyList(),
    val selectedTab: TabEntity = TabEntity.TodoEvaluation,
    val pageData: List<TodoTask> = emptyList(),
)

data class FilterData(
    val subjectList: MutableList<DrawerContent.SubjectContent> = arrayListOf(),
    val reviewList: MutableList<DrawerContent.ReviewContent> = arrayListOf(),
    val timeList: MutableList<DrawerContent.TimeContent> = arrayListOf()
)

data class FilterSelection(
    val subjectIndex: Int = 0,
    val reviewIndex: Int = 0,
    val timeIndex: Int = 0
)

@Stable
sealed class TabEntity(
    @StringRes val label: Int,
    @DrawableRes val imageUnselected: Int,
    @DrawableRes val imageSelected: Int
) {
    object TodoEvaluation : TabEntity(
        label = R.string.evaluation_todo,
        imageUnselected = R.drawable.ic_icon_not_assessment,
        imageSelected = R.drawable.ic_icon_not_assessment_hover
    )

    object Correcting : TabEntity(
        label = R.string.correcting,
        imageUnselected = R.drawable.ic_icon_correction,
        imageSelected = R.drawable.ic_icon_correction_hover
    )

    object TodoCorrection : TabEntity(
        label = R.string.correction_todo,
        imageUnselected = R.drawable.ic_icon_not_done_revising,
        imageSelected = R.drawable.ic_icon_not_done_revising_hover
    )

    object CorrectAgain : TabEntity(
        label = R.string.correct_again,
        imageUnselected = R.drawable.ic_icon_correction,
        imageSelected = R.drawable.ic_icon_correction_hover
    )

    object EvaluationDone : TabEntity(
        label = R.string.evaluation_done,
        imageUnselected = R.drawable.ic_icon_completed,
        imageSelected = R.drawable.ic_icon_completed_hover
    )
}

sealed class HomeAction {
    data class Search(val keywords: String) : HomeAction()
    data class FilterSelect(val drawerContent: DrawerContent, val index: Int) : HomeAction()
    object FilterReset : HomeAction()
    data class TabSwitch(val tabEntity: TabEntity) : HomeAction()
}
